package template

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

type Template struct {
	OwAll       bool              // 是否全部覆盖
	Path        string            // 模版路径
	SymbolLeft  string            // 模版变量边界符号
	SymbolRight string            // 模版变量边界符号
	vmap        map[string]string // 模版变量
}

// 初始化模版
func Initialize() (tpl *Template) {
	return &Template{
		OwAll: false,
		Path:  "",
		vmap:  make(map[string]string),
	}
}

// 设置模版变量
func (tpl *Template) SetEnv(key string, val string) {
	tpl.vmap[key] = val
}

// 设置模版变量
func (tpl *Template) SetPath(path string) {
	tpl.Path = path
}

func (tpl *Template) Check() error {
	// 检查模版路径
	_, err := os.Stat(tpl.Path)
	if err != nil {
		return err
	}

	return nil
}

// 扫描模版
func (tpl *Template) Grow() {
	reader := bufio.NewReader(os.Stdin)

	err := filepath.Walk(tpl.Path, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf("[错误] %s\n", err)
			return err
		}

		// 过滤出 .md 文件
		if !info.IsDir() && filepath.Ext(path) == ".md" {

			// fmt.Printf("发现模版文件: %s\n", path)

			// 解析模版文件
			ptf, err := paserTemplateFile(path)
			if err == nil {
				// 获取需要创建文件的真实路径
				targePath := tpl.ReplaceVars(ptf.filePath)
				targeVal := tpl.ReplaceVars(ptf.s.String())

				// fmt.Println(">>>>", targePath)
				// fmt.Println(targeVal)

				// 询问是否覆盖文件
				exist := fileExist(ptf.filePath)
				if tpl.OwAll != true && exist {
					// 询问是否覆盖文件
					fmt.Printf("[警告] %s 文件已存在, 是否覆盖(y/n)? ", ptf.filePath)
					input, _ := reader.ReadString('\n')

					// 不覆盖文件跳过处理
					input = strings.ToLower(strings.TrimSpace(input))
					if input == "n" || input == "no" {
						return nil
					}
				}

				// 写入文件
				err := writeFile(targePath, []byte(targeVal))
				if err == nil {
					fmt.Printf("创建文件: %s\n", targePath)
					return nil
				}

				fmt.Printf("[错误]: %s\n", err)
			}
		}

		return nil
	})

	if err != nil {
		fmt.Printf("遍历目录时出错: %v\n", err)
	}
}

// 使用模版变量替换内容
func (tpl *Template) ReplaceVars(s string) string {
	for k, v := range tpl.vmap {
		s = strings.ReplaceAll(s, tpl.SymbolLeft+k+tpl.SymbolRight, v)
	}

	return s
}

func fileExist(file string) bool {
	_, err := os.Stat(file)

	if err == nil {
		return true
	}

	return false
}

func writeFile(file string, data []byte) error {

	dir := filepath.Dir(file)
	_, e := os.Stat(dir)
	if e != nil {
		if os.IsNotExist(e) {
			os.MkdirAll(dir, 0755)
		}
	}

	return os.WriteFile(file, []byte(data), 0644)
}
